﻿var spa = spa || {};

spa.entityStates = {
    /// <summary>
    /// The States that a Self-Tracking Entity would Need
    /// <summary>
    unchanged: "unchanged", // Persisted, not changed
    added: "added", // Added, not saved
    removed: "removed", // Removed, not saved
    modified: "modified" // Changed, not saved
};

spa.dataEntity = function (data, initialState) {
    var self = this;
    self._origData = data;
    self._persistData = null;
    self.Entity = ko.mapping.fromJS(data);
    self.EntityState = ko.observable(initialState || spa.entityStates.unchanged);
    self.IsSubmitting = ko.observable(false);
    self.HasChanges = ko.computed(function () {
        for (var prop in self._origData) {
            if (self._origData[prop] != ko.utils.unwrapObservable(self.Entity[prop])) {
                if (self.EntityState() == spa.entityStates.unchanged) {
                    self.EntityState(spa.entityStates.modified);
                }
                return true;
            }
        }
        if (self.EntityState() == spa.entityStates.modified) {
            self.EntityState(spa.entityStates.unchanged);
        }
        return false;
    });
};

spa.dataEntity.prototype = {
    Update: function (data) {
        /// <summary>
        /// Updates the Entity (overwrites any pending changes)
        /// </summary>
        /// <param name="data" type="JSON">
        /// Required: New Data for the entity
        /// </param>
        this._origData = data;
        for (prop in data) {
            if (data[prop] != ko.utils.unwrapObservable(this.Entity[prop])) {
                this.Entity[prop](data[prop]);
            }
        }
        this.EntityState(spa.entityStates.unchanged);
    },
    Merge: function (data) {
        /// <summary>
        /// Updates the Entity (preserves any pending changes since the last ToJSON call)
        /// </summary>
        /// <param name="data" type="JSON">
        /// Required: New Data for the entity
        /// </param>

        // Get List of Modifications since the data
        var newMods = false;        
        var lastSubmit = JSON.parse(this._persistData) || this._origData;
        for (prop in data) {
            if (lastSubmit[prop] != data[prop]) {
                newMods = true;
                break;
            }
        }
        // Only Update Properties which are not currently modified
        this._origData = data;
        for (prop in data) {
            if (data[prop] != ko.utils.unwrapObservable(this.Entity[prop])) {
                this.Entity[prop](data[prop]);
            }
        }
        if (newMods == false) {
            this.EntityState(spa.entityStates.unchanged);
        }
        else {
            this.EntityState(spa.entityStates.modified);
        }
    },
    ToJSON: function () {
        /// <summary>
        /// Gets JSON value of the Entity (sets change tracking marker)
        /// </summary>
        /// <return>
        /// JSON String
        /// </return>
        this._persistData = ko.mapping.toJSON(this.Entity);
        return this._persistData;
    },
};